package com.sqtracker.recommender.service;

import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.model.Filters;
import com.sqtracker.recommender.algorithm.ContentBasedRecommender;
import com.sqtracker.recommender.algorithm.ItemCFRecommender;
import com.sqtracker.recommender.model.TorrentMetadataExt;
import com.sqtracker.recommender.repository.TorrentMetadataExtRepository;
import org.bson.Document;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class TorrentMetadataSyncService {

    private static final Logger logger = LoggerFactory.getLogger(TorrentMetadataSyncService.class);

    private final MongoClient mongoClient;
    private final TorrentMetadataExtRepository torrentMetadataExtRepository;
    private final ItemCFRecommender itemCFRecommender;
    private final ContentBasedRecommender contentBasedRecommender;

    @Value("${mongodb.database.source:sqtracker}")
    private String sourceDatabase;

    @Value("${mongodb.collection.torrents:torrents}")
    private String torrentsCollection;

    @Autowired
    public TorrentMetadataSyncService(
            MongoClient mongoClient,
            TorrentMetadataExtRepository torrentMetadataExtRepository,
            ItemCFRecommender itemCFRecommender,
            ContentBasedRecommender contentBasedRecommender) {
        this.mongoClient = mongoClient;
        this.torrentMetadataExtRepository = torrentMetadataExtRepository;
        this.itemCFRecommender = itemCFRecommender;
        this.contentBasedRecommender = contentBasedRecommender;
    }

    /**
     * 每6小时运行一次全量同步
     */
    @Scheduled(fixedRate = 6 * 60 * 60 * 1000)
    public void scheduledFullSync() {
        try {
            logger.info("Starting scheduled full torrent metadata sync");
            int count = syncAllTorrents();
            logger.info("Completed scheduled full sync. Processed {} torrents", count);

            // 重新计算相似度矩阵
            itemCFRecommender.computeItemSimilarityMatrix();
            // 清理内容推荐器的向量缓存
            contentBasedRecommender.clearVectorCache();
        } catch (Exception e) {
            logger.error("Error during scheduled full sync", e);
        }
    }

    /**
     * 每30分钟运行一次增量同步
     */
    @Scheduled(fixedRate = 30 * 60 * 1000)
    public void scheduledIncrementalSync() {
        try {
            logger.info("Starting incremental torrent metadata sync");
            // 获取24小时内更新的种子
            Date oneDayAgo = new Date(System.currentTimeMillis() - 24 * 60 * 60 * 1000);
            int count = syncRecentTorrents(oneDayAgo);
            logger.info("Completed incremental sync. Processed {} recent torrents", count);
        } catch (Exception e) {
            logger.error("Error during incremental sync", e);
        }
    }

    /**
     * 同步所有种子数据
     */
    public int syncAllTorrents() {
        logger.info("Starting full torrent metadata sync");
        MongoCollection<Document> collection = mongoClient
                .getDatabase(sourceDatabase)
                .getCollection(torrentsCollection);

        int processed = 0;
        int updated = 0;
        int created = 0;

        try (MongoCursor<Document> cursor = collection.find().iterator()) {
            while (cursor.hasNext()) {
                Document torrentDoc = cursor.next();
                processed++;

                String torrentId = torrentDoc.getObjectId("_id").toString();
                if (processed % 1000 == 0) {
                    logger.info("Processing torrent {}: {}", processed, torrentId);
                }

                // 检查是否已存在
                Optional<TorrentMetadataExt> existingOpt = torrentMetadataExtRepository.findByTorrentId(torrentId);

                TorrentMetadataExt metadata;
                if (existingOpt.isPresent()) {
                    metadata = existingOpt.get();
                    updated++;
                } else {
                    metadata = new TorrentMetadataExt();
                    metadata.setTorrentId(torrentId);
                    created++;
                }

                // 填充元数据
                updateMetadataFromDocument(metadata, torrentDoc);

                // 保存到数据库
                torrentMetadataExtRepository.save(metadata);
            }
        }

        logger.info("Completed full sync. Processed: {}, Updated: {}, Created: {}",
                processed, updated, created);
        return processed;
    }

    /**
     * 同步最近更新的种子
     */
    public int syncRecentTorrents(Date since) {
        logger.info("Starting recent torrents sync since {}", since);
        MongoCollection<Document> collection = mongoClient
                .getDatabase(sourceDatabase)
                .getCollection(torrentsCollection);

        // 查找近期更新的种子
        int processed = 0;
        try (MongoCursor<Document> cursor = collection.find(
                Filters.gt("created", since.getTime() / 1000)).iterator()) {

            while (cursor.hasNext()) {
                Document torrentDoc = cursor.next();
                String torrentId = torrentDoc.getObjectId("_id").toString();

                // 检查是否已存在
                Optional<TorrentMetadataExt> existingOpt = torrentMetadataExtRepository.findByTorrentId(torrentId);

                TorrentMetadataExt metadata;
                if (existingOpt.isPresent()) {
                    metadata = existingOpt.get();
                } else {
                    metadata = new TorrentMetadataExt();
                    metadata.setTorrentId(torrentId);
                }

                // 填充元数据
                updateMetadataFromDocument(metadata, torrentDoc);

                // 保存到数据库
                torrentMetadataExtRepository.save(metadata);
                processed++;
            }
        }

        logger.info("Completed recent sync. Processed {} torrents", processed);
        return processed;
    }

    /**
     * 根据原始种子文档更新元数据对象
     */
    private void updateMetadataFromDocument(TorrentMetadataExt metadata, Document doc) {
        // 基础数据映射
        try {
            // 设置标签
            if (doc.containsKey("tags") && doc.get("tags") instanceof List) {
                List<String> tags = new ArrayList<>();
                for (Object tag : (List<?>) doc.get("tags")) {
                    if (tag != null) {
                        tags.add(tag.toString());
                    }
                }
                metadata.setTags(tags);
            }

            // 设置种子类型作为类别ID
            if (doc.containsKey("type")) {
                metadata.setTorrentCategoryId(doc.getString("type"));
            }

            // 更新时间
            if (doc.containsKey("created")) {
                Long createdTime = doc.getLong("created");
                if (createdTime != null) {
                    metadata.setLastUpdated(new Date(createdTime * 1000)); // 转换为毫秒
                }
            } else {
                metadata.setLastUpdated(new Date());
            }

            // 处理下载量计算热度
            if (doc.containsKey("downloads")) {
                Integer downloads = doc.getInteger("downloads");
                if (downloads != null) {
                    // 简单的流行度算法，可以根据业务需求调整
                    double popularity = Math.min(1.0, Math.log10(downloads + 1) / 6.0);
                    metadata.setPopularity(popularity);
                }
            } else {
                metadata.setPopularity(0.1); // 默认值
            }

            // 计算新鲜度 (10天内为新内容，线性下降)
            Date now = new Date();
            Date lastUpdated = metadata.getLastUpdated();
            if (lastUpdated != null) {
                long diffDays = (now.getTime() - lastUpdated.getTime()) / (1000 * 60 * 60 * 24);
                double freshness = Math.max(0.0, 1.0 - (diffDays / 10.0));
                metadata.setFreshness(freshness);
            } else {
                metadata.setFreshness(0.5); // 默认中等新鲜度
            }

            // 从MediaInfo尝试提取语言和质量信息
            if (doc.containsKey("mediaInfo") && doc.getString("mediaInfo") != null) {
                String mediaInfo = doc.getString("mediaInfo");
                extractMediaInfo(metadata, mediaInfo);
            }

            // 计算发布者声誉 (可选，需要使用上传者ID关联用户信息)
            if (doc.containsKey("uploadedBy")) {
                String uploaderId = doc.get("uploadedBy").toString();
                double reputation = calculatePublisherReputation(uploaderId);
                metadata.setPublisherReputation(reputation);
            } else {
                metadata.setPublisherReputation(0.5); // 默认中等声誉
            }
        } catch (Exception e) {
            logger.error("Error updating metadata for torrentId {}: {}",
                    metadata.getTorrentId(), e.getMessage());
        }
    }

    /**
     * 从MediaInfo提取语言和质量信息
     */
    private void extractMediaInfo(TorrentMetadataExt metadata, String mediaInfo) {
        if (mediaInfo == null || mediaInfo.isEmpty()) {
            return;
        }

        // 简单解析MediaInfo提取语言和质量
        // 实际项目中应该使用更复杂的解析逻辑
        String lowerMediaInfo = mediaInfo.toLowerCase();

        // 检测语言
        if (lowerMediaInfo.contains("chinese") || lowerMediaInfo.contains("mandarin")) {
            metadata.setLanguage("zh");
        } else if (lowerMediaInfo.contains("english")) {
            metadata.setLanguage("en");
        } else if (lowerMediaInfo.contains("japanese")) {
            metadata.setLanguage("ja");
        } else if (lowerMediaInfo.contains("korean")) {
            metadata.setLanguage("ko");
        }

        // 检测质量
        if (lowerMediaInfo.contains("4k") || lowerMediaInfo.contains("2160p")) {
            metadata.setQuality("4K");
        } else if (lowerMediaInfo.contains("1080p")) {
            metadata.setQuality("1080p");
        } else if (lowerMediaInfo.contains("720p")) {
            metadata.setQuality("720p");
        } else if (lowerMediaInfo.contains("480p")) {
            metadata.setQuality("480p");
        }

        // 提取字幕
        List<String> subtitles = new ArrayList<>();
        if (lowerMediaInfo.contains("chinese subtitle") || lowerMediaInfo.contains("中文")) {
            subtitles.add("zh");
        }
        if (lowerMediaInfo.contains("english subtitle") || lowerMediaInfo.contains("英文")) {
            subtitles.add("en");
        }
        if (!subtitles.isEmpty()) {
            metadata.setSubtitles(subtitles);
        }
    }

    /**
     * 计算发布者声誉 (简单实现)
     */
    private double calculatePublisherReputation(String uploaderId) {
        // 简单起见，这里返回一个默认值
        // 实际项目中应该根据上传者的历史记录计算
        return 0.7;
    }

    /**
     * 立即执行一次同步 (可以通过API触发)
     */
    public Map<String, Object> forceSyncNow() {
        Map<String, Object> result = new HashMap<>();
        try {
            result.put("startTime", new Date());
            int count = syncAllTorrents();
            result.put("torrentCount", count);
            result.put("status", "success");
            result.put("endTime", new Date());

            // 重新计算相似度矩阵
            itemCFRecommender.computeItemSimilarityMatrix();
            contentBasedRecommender.clearVectorCache();

            return result;
        } catch (Exception e) {
            logger.error("Error during forced sync", e);
            result.put("status", "error");
            result.put("message", e.getMessage());
            return result;
        }
    }
}